import os
import uuid
import wtforms
from flask import Blueprint, jsonify, render_template, request, redirect, session, url_for
from sqlalchemy.testing.pickleable import User
from werkzeug.utils import secure_filename

from exts import mail, db, login_manager  # 确保导入 login_manager
from flask_mail import Message
import string, random
from models import EmailCaptchaModel, UserModel, ImageCaptchaModel, Log
from .ec import log_behavior
from .forms import RegisterForm, LoginForm
from werkzeug.security import generate_password_hash, check_password_hash

from flask import send_file
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime, timedelta
from flask_login import login_user

bp = Blueprint('auth', __name__, url_prefix='/auth')


@bp.route("/login", methods=['GET', 'POST'])
def login():
    if request.method == "GET":
        return render_template("register.html")
    else:
        form = LoginForm(request.form)
        if form.validate():
            email = form.email.data
            password = form.password.data
            image_captcha = request.form.get("image_captcha")

            # 验证图片验证码
            captcha_model = ImageCaptchaModel.query.filter_by(captcha_text=image_captcha).first()
            if not captcha_model:
                return jsonify({"code": 400, "message": "图片验证码错误"})

            # 检查验证码是否过期（5分钟有效期）
            expiration_time = captcha_model.created_time + timedelta(minutes=5)
            if datetime.now() > expiration_time:
                db.session.delete(captcha_model)
                db.session.commit()
                return jsonify({"code": 400, "message": "图片验证码已过期，请刷新重试"})

            # 验证通过后删除验证码
            db.session.delete(captcha_model)
            db.session.commit()

            # 用户验证流程
            user = UserModel.query.filter_by(email=email).first()
            if not user:
                return jsonify({"code": 400, "message": "邮箱或密码错误"})
            if check_password_hash(user.password, password):
                login_user(user)  # 使用 Flask-Login 登录用户
                session["user_id"] = user.id
                log_behavior(user.id, '用户登录', f'用户 {user.username} 登录系统')
                return jsonify({
                    "code": 200,
                    "message": "登录成功",
                    "redirect": url_for('ec.index')  # 添加跳转URL
                })
            else:
                return jsonify({"code": 400, "message": "邮箱或密码错误"})
        else:
            # 提取表单错误信息
            errors = {field: error_list[0] for field, error_list in form.errors.items()}
            return jsonify({"code": 400, "message": errors})


# 添加用户加载器
@login_manager.user_loader
def load_user(user_id):
    return UserModel.query.get(int(user_id))


# 对验证码有效期的检查
def validate_captcha(self, field):
    captcha = field.data
    email = self.email.data
    captcha_model = EmailCaptchaModel.query.filter_by(email=email, captcha=captcha).first()

    if not captcha_model:
        raise wtforms.ValidationError(message="邮箱或验证码错误！")

    # 检查验证码是否过期（10分钟有效期）
    expiration_time = captcha_model.created_time + timedelta(minutes=10)
    if datetime.now() > expiration_time:
        db.session.delete(captcha_model)  # 删除过期的验证码
        db.session.commit()
        raise wtforms.ValidationError(message="验证码已过期，请重新获取！")


@bp.route("/captcha/image")
def get_image_captcha():
    # 生成随机验证码文本
    captcha_text = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))

    # 创建图片
    image = Image.new('RGB', (120, 40), color=(255, 255, 255))
    draw = ImageDraw.Draw(image)
    font = ImageFont.load_default()
    draw.text((10, 10), captcha_text, font=font, fill=(0, 0, 0))

    # 将图片保存到内存中
    buf = BytesIO()
    image.save(buf, format='PNG')
    buf.seek(0)

    # 将验证码文本存储到数据库，设置5分钟有效期
    captcha_model = ImageCaptchaModel(
        id=str(uuid.uuid4()),
        captcha_text=captcha_text,
        created_time=datetime.now()
    )
    db.session.add(captcha_model)
    db.session.commit()

    # 清理过期验证码
    cleanup_expired_image_captchas()

    # 返回图片
    return send_file(buf, mimetype='image/png')


def cleanup_expired_image_captchas():
    """清理过期的图片验证码"""
    expiration_time = datetime.now() - timedelta(minutes=5)
    expired_captchas = ImageCaptchaModel.query.filter(
        ImageCaptchaModel.created_time < expiration_time
    ).all()
    for captcha in expired_captchas:
        db.session.delete(captcha)
    db.session.commit()


# 退出登录
@bp.route("/logout")
def logout():
    user_id = session.get("user_id")
    if user_id:
        user = UserModel.query.get(user_id)
        # 记录用户退出日志
        log_behavior(user_id, '用户退出', f'用户 {user.username} 退出系统')
    session.clear()  # 清除 session
    return redirect("/")


# GET:从服务器上获取数据
# POST:将客户端的数据提交给服务器

@bp.route("/register", methods=['GET', 'POST'])
def register():
    if request.method == "GET":
        return render_template("register.html")
    else:
        form = RegisterForm(request.form)
        if form.validate():
            email = form.email.data
            username = form.username.data
            password = form.password.data
            user = UserModel(email=email, username=username, password=generate_password_hash(password))
            session["user_id"] = user.id
            db.session.add(user)
            db.session.commit()
            # 记录用户注册日志
            log_behavior(user.id, '用户注册', f'用户 {username} 注册成功')
            return jsonify({"code": 200, "message": "注册成功"})
        else:
            print(form.errors)
            return jsonify({"code": 400, "message": form.errors})
    # 验证用户提交的邮箱和验证码是否对应且正确
    # 表单验证:flask-wtf: wtforms


# bp.route:如果没有指定methods参数，默认就是GET请求
@bp.route("/captcha/email", methods=['GET', 'POST'])
def get_email_captcha():
    # /captcha/email/<email>
    # /captcha/email?email=xxx@qq.com

    email = request.args.get("email")
    # 生成6位数字验证码
    source = string.digits * 6
    captcha = random.sample(source, 6)
    captcha = ''.join(captcha)
    # I / O 操作 发送邮件
    message = Message(subject="电商平台用户行为预测系统", recipients=[email],
                      body=f"【电商平台用户行为预测系统】验证码：{captcha}，您正在进行注册效验，请勿将验证码泄露与他人，验证码5分钟内有效。")
    mail.send(message)
    # memcached / redis
    # 存储验证码到数据库，设置5分钟有效期
    email_captcha = EmailCaptchaModel(email=email, captcha=captcha)
    db.session.add(email_captcha)
    db.session.commit()
    # 启动后台任务清理过期验证码
    cleanup_expired_email_captchas()

    # RESTful API
    # {code: 200/400/500, message:"", data: {}}
    return jsonify({"code": 200, "message": "", "data": None})


def cleanup_expired_email_captchas():
    """清理过期的邮箱验证码"""
    expiration_time = datetime.now() - timedelta(minutes=5)
    expired_captchas = EmailCaptchaModel.query.filter(
        EmailCaptchaModel.created_time < expiration_time
    ).all()
    for captcha in expired_captchas:
        db.session.delete(captcha)
    db.session.commit()


# user
# 配置头像上传
AVATAR_UPLOAD_FOLDER = 'static/uploads/avatars'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}


def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@bp.route('/update_profile', methods=['POST'])
def update_profile():
    if 'user_id' not in session:
        return jsonify({'success': False, 'message': '请先登录'})

    user = UserModel.query.get(session['user_id'])
    if not user:
        return jsonify({'success': False, 'message': '用户不存在'})

    # 更新用户信息
    user.username = request.form.get('username', user.username)
    user.email = request.form.get('email', user.email)
    user.first_name = request.form.get('first_name', user.first_name)
    user.last_name = request.form.get('last_name', user.last_name)
    user.address = request.form.get('address', user.address)
    user.city = request.form.get('city', user.city)
    user.country = request.form.get('country', user.country)
    user.postal_code = request.form.get('postal_code', user.postal_code)
    user.bio = request.form.get('bio', user.bio)

    db.session.commit()

    log_behavior(user.id, '更新个人信息')
    return jsonify({'success': True, 'message': '个人信息更新成功'})


@bp.route('/change_password', methods=['POST'])
def change_password():
    if 'user_id' not in session:
        return jsonify({'success': False, 'message': '请先登录'})

    user = UserModel.query.get(session['user_id'])
    if not user:
        return jsonify({'success': False, 'message': '用户不存在'})

    current_password = request.form.get('current_password')
    new_password = request.form.get('new_password')
    confirm_password = request.form.get('confirm_password')

    if not check_password_hash(user.password, current_password):
        return jsonify({'success': False, 'message': '当前密码不正确'})

    if new_password != confirm_password:
        return jsonify({'success': False, 'message': '两次输入的新密码不一致'})

    if len(new_password) < 8:
        return jsonify({'success': False, 'message': '密码长度至少为8位'})

    user.password = generate_password_hash(new_password)
    db.session.commit()

    log_behavior(user.id, '修改密码')
    return jsonify({'success': True, 'message': '密码修改成功'})


@bp.route('/upload_avatar', methods=['POST'])
def upload_avatar():
    if 'user_id' not in session:
        return jsonify({'success': False, 'message': '请先登录'})

    if 'avatar' not in request.files:
        return jsonify({'success': False, 'message': '未选择文件'})

    file = request.files['avatar']
    if file.filename == '':
        return jsonify({'success': False, 'message': '未选择文件'})

    if file and allowed_file(file.filename):
        # 确保上传目录存在
        if not os.path.exists(AVATAR_UPLOAD_FOLDER):
            os.makedirs(AVATAR_UPLOAD_FOLDER)

        # 生成安全的文件名
        filename = secure_filename(
            f"{session['user_id']}_{datetime.now().strftime('%Y%m%d%H%M%S')}.{file.filename.rsplit('.', 1)[1].lower()}")
        filepath = os.path.join(AVATAR_UPLOAD_FOLDER, filename)
        file.save(filepath)

        # 更新用户头像路径
        user = UserModel.query.get(session['user_id'])
        user.avatar_url = f"/uploads/avatars/{filename}"
        db.session.commit()

        log_behavior(user.id, '上传头像', f'新头像: {filename}')
        return jsonify({'success': True, 'message': '头像上传成功', 'avatar_url': user.avatar_url})

    return jsonify({'success': False, 'message': '不支持的文件类型'})
